package com.sayyi.demo.micro.order.service.impl;

import com.sayyi.demo.micro.order.convertor.OrderConvertor;
import com.sayyi.demo.micro.order.entity.OrderTbl;
import com.sayyi.demo.micro.order.mapper.OrderTblMapper;
import com.sayyi.demo.micro.order.service.IOrderTblService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sayyi.demo.micro.order.service.OrderTccService;
import com.sayyi.demo.micro.storage.api.StorageApi;
import com.sayyi.demo.micro.storage.domain.UpdateStorageRequest;
import io.seata.saga.engine.StateMachineEngine;
import io.seata.saga.statelang.domain.ExecutionStatus;
import io.seata.saga.statelang.domain.StateMachineInstance;
import io.seata.spring.annotation.GlobalTransactional;
import io.seata.tm.api.GlobalTransactionContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2022-02-21
 */
@Service
@Slf4j
public class OrderTblServiceImpl extends ServiceImpl<OrderTblMapper, OrderTbl> implements IOrderTblService {

    @DubboReference(version = "1.0.0")
    private StorageApi storageApi;

    @Autowired
    private OrderConvertor orderConvertor;

    @Autowired
    private OrderTccService service;

    @Override
    @GlobalTransactional
    public int createOrder(OrderTbl orderTbl) {
        this.save(orderTbl);
        UpdateStorageRequest request = orderConvertor.orderToStorageRequest(orderTbl);
        storageApi.updateStorage(request);
        return orderTbl.getId();
    }

    @Override
    @GlobalTransactional
    public int createOrderByTcc(OrderTbl orderTbl) {
        return service.createOrder(null, orderTbl);
    }

    @Autowired
    private StateMachineEngine stateMachineEngine;

    private final AtomicInteger simpleIdUtil = new AtomicInteger(1);

    @Override
    @GlobalTransactional
    public int createOrderBySaga(OrderTbl orderTbl) {
        // 异步执行，需要提前给id，让saga进行幂等校验
        orderTbl.setId(simpleIdUtil.getAndIncrement());

        Map<String, Object> params = new HashMap<>();
        params.put("orderEntry", orderTbl);
        params.put("storageRequest", orderConvertor.orderToStorageRequest(orderTbl));

        String businessKey = String.valueOf(System.currentTimeMillis());
        StateMachineInstance instance = stateMachineEngine.startWithBusinessKey("create_order", null, businessKey, params);
        if (ExecutionStatus.SU.equals(instance.getStatus())) {
            log.info("订单创建成功[{}]", instance.getId());
//            try {
//                GlobalTransactionContext.reload(instance.getId()).commit();
//            } catch (Exception e) {
//                log.warn("手动提交事务异常", e);
//            }
        } else {
            log.error("订单创建异常[{}]", instance.getId());
            throw new RuntimeException("订单创建异常");
        }
        return Integer.parseInt(instance.getContext().get("orderId").toString());
    }
}
